import {Base, props} from '../util';

export class Container extends Base {

  template(prop = 'tpl') {
    if (!_.isFunction(this[prop])) {
      let val = this[prop];
      delete this[prop];
      _.isArray(val) && (val = val.join(''));
      if (!_.isString(val)) {
        throw new Error(`The "${prop}" template is not valid`);
      }
      // compile the template only once for all instances of a component
      Object.getPrototypeOf(this)[prop] = _.template(val);
    }
    return this[prop](this);
  }

  createEl() {
    var el = $(this.template());
    if (el && (1 === el.length) && _.isElement(el[0])) return el;
    throw new Error('The template is not valid');
  }

  show() {
    if (this.el) {
      this.visMode ? this.el.css('visibility', 'visible') : this.el.show();
    } else {
      this.el = this.createEl();
      this.fire('beforeRender');
      this.parent[this.prependMode ? 'prepend' : 'append'](this.el);
      this.fire('render');
    }
    this.fire('show');
  }

  hide() {
    if (this.el && this.fire('beforeHide')) {
      this.visMode ? this.el.css('visibility', 'hidden') : this.el.hide();
      this.fire('hide');
    }
  }

  up(type) {
    var owner = this.owner;
    while (owner) {
      if (!type || owner instanceof type) return owner;
      owner = owner.owner;
    }
  }

  animate(cls, el) {
    if (el = el || this.el) {
      cls += ' animated';
      el = $(el);
      el.removeClass(cls).addClass(cls).one('webkitAnimationEnd mozAnimationEnd'
        + ' MSAnimationEnd oanimationend animationend', () => {
          el.removeClass(cls);
        });
    }
  }

  get width() { return this.el && this.el.width() }

  set width(val) { this.el && this.el.width(val) }

  get height() { return this.el && this.el.height() }

  set height(val) { this.el && this.el.height(val) }

  set css(val) { this.el && this.el.css(val) }

}

props(Container, {tpl: () => '', visMode: false, prependMode: false});
$(() => { props(Container, {parent: $('body')}) });